package com.feishu.rpc.http;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.feishu.base.dto.HttpClientTokenDTO;
import com.feishu.base.dto.entity.ExecutionTypeDO;
import com.feishu.rpc.http.config.RpcHttpConfig;
import com.feishu.rpc.http.service.RemoteCallBack;
import com.feishu.rpc.http.service.RemoteProcedureCallService;
import com.feishu.rpc.http.service.RemoteProcedureChangeCallService;
import com.feishu.rpc.http.service.RemoteProcedureNodeCallService;
import com.feishu.rpc.utils.HttpMethodEnum;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Map;

@Service
public class RemoteSocketWrapper {
    public JSONObject httpPostMethodToJSONObject(ExecutionTypeDO executionTypeDO, HttpMethodEnum httpMethodEnum, String uri, JSONObject parameter, HttpClientTokenDTO httpClientTokenDTO, RemoteCallBack remoteCallBack
            , RemoteProcedureCallService remoteProcedureCallService) throws Exception{
        String url=httpMethodEnum.value()+uri;

        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig=RequestConfig.custom().setConnectTimeout(
                RpcHttpConfig.connectTimeout).setSocketTimeout(RpcHttpConfig.socketTimeout).build();
        httpPost.setConfig(requestConfig);
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        CloseableHttpResponse response = null;

        try {

            httpPost.setHeader("Content-Type","application/json; charset=utf-8");
            httpPost.setHeader("Connection","close");
            remoteProcedureCallService.changeHttpClientHeaders(httpClientTokenDTO,httpPost,executionTypeDO);

            JSONObject obj=null;
            if(parameter!=null){
                obj= parameter;
                String send=obj.toString();
                StringEntity byteArrayEntity=new StringEntity(changeCharset(send, "ISO-8859-1"));
                Header[] header=httpPost.getHeaders("Content-Type");
                if(header!=null && header.length>0){
                    StringBuilder stringBuilder=new StringBuilder();
                    for(int i=0;i<header.length;i++){
                        if(i>0) stringBuilder.append("; ");
                        stringBuilder.append(header[i].getValue());
                    }
                    byteArrayEntity.setContentType(stringBuilder.toString());
                }
                else{
                    byteArrayEntity.setContentType("application/json; charset=utf-8");
                }
                httpPost.setEntity(byteArrayEntity);
            }

            response = httpClient.execute(httpPost);
            if(remoteCallBack!=null){
                remoteCallBack.callBack(response);
            }
            else{
                int status = response.getStatusLine().getStatusCode();
                if (status == HttpStatus.SC_OK) {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {

                        JSONObject result=null;
                        String resultStr= EntityUtils.toString(entity);
                        try {
                            result=JSONObject.parseObject(resultStr);
                        }
                        catch (Exception e){
                            e.printStackTrace();
                        }

                        return result;
                    }
                }
                else{
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        return JSONObject.parseObject(EntityUtils.toString(entity));
                    }
                }
            }
        }
        finally {
            if (response != null) {
                try {
                    response.close();
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    public JSONObject httpGetMethodToJSONObject(ExecutionTypeDO executionTypeDO,HttpMethodEnum httpMethodEnum, String uri, HttpClientTokenDTO httpClientTokenDTO, RemoteCallBack remoteCallBack) throws Exception{
        RemoteProcedureCallService remoteProcedureCallService=SpringUtil.getBean(RemoteProcedureCallService.class);

        String url=httpMethodEnum.value()+uri;


        HttpGet httpGet = new HttpGet(url);
        RequestConfig requestConfig=RequestConfig.custom().setConnectTimeout(RpcHttpConfig.connectTimeout).setSocketTimeout(RpcHttpConfig.socketTimeout).build();
        httpGet.setConfig(requestConfig);
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        CloseableHttpResponse response = null;

        try {

            httpGet.setHeader("Content-Type","application/json; charset=utf-8");
            httpGet.setHeader("Connection","close");
            remoteProcedureCallService.changeHttpClientHeaders(httpClientTokenDTO,httpGet,executionTypeDO);

            response = httpClient.execute(httpGet);
            if(remoteCallBack!=null){
                remoteCallBack.callBack(response);
            }
            else{
                int status = response.getStatusLine().getStatusCode();
                if (status == HttpStatus.SC_OK) {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {

                        JSONObject result=null;
                        String resultStr= EntityUtils.toString(entity);
                        try {
                            result=JSONObject.parseObject(resultStr);
                        }
                        catch (Exception e){
                            e.printStackTrace();
                        }

                        return result;
                    }
                }
                else{
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        return JSONObject.parseObject(EntityUtils.toString(entity));
                    }
                }
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            if (response != null) {
                try {
                    response.close();
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    public String changeCharset(String str, String newCharset) {
        try {
            if (str != null) {
                //用默认字符编码解码字符串。
                byte[] bs = str.getBytes();
                //用新的字符编码生成字符串
                return new String(bs, newCharset);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        return null;
    }
    public  JSONObject httpPostMethodToJSONObject(ExecutionTypeDO executionTypeDO,HttpMethodEnum httpMethodEnum, String uri, Map<String,Object> parameter, HttpClientTokenDTO httpClientTokenDTO, RemoteCallBack remoteCallBack
    ,RemoteProcedureCallService remoteProcedureCallService) throws Exception{

        StringBuilder url=new StringBuilder();
        url.append(httpMethodEnum.value());
        url.append(uri);

        HttpPost httpPost = new HttpPost(url.toString());
        RequestConfig requestConfig=RequestConfig.custom().setConnectTimeout(RpcHttpConfig.connectTimeout).setSocketTimeout(RpcHttpConfig.socketTimeout).build();
        httpPost.setConfig(requestConfig);
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        CloseableHttpResponse response = null;

        try {

            httpPost.setHeader("Content-Type","application/json; charset=utf-8");
            httpPost.setHeader("Connection","close");

            remoteProcedureCallService.changeHttpClientHeaders(httpClientTokenDTO,httpPost,executionTypeDO);

            JSONObject obj=null;
            if(parameter!=null){
                obj= JSONObject.parseObject(JSONObject.toJSONString(parameter));
                String send=obj.toString();
                StringEntity byteArrayEntity=new StringEntity(changeCharset(send,"ISO-8859-1"));
                Header[] header=httpPost.getHeaders("Content-Type");
                if(header!=null && header.length>0){
                    StringBuilder stringBuilder=new StringBuilder();
                    for(int i=0;i<header.length;i++){
                        if(i>0) stringBuilder.append("; ");
                        stringBuilder.append(header[i].getValue());
                    }
                    byteArrayEntity.setContentType(stringBuilder.toString());
                }
                else{
                    byteArrayEntity.setContentType("application/json; charset=utf-8");
                }
                httpPost.setEntity(byteArrayEntity);

            }



            response = httpClient.execute(httpPost);
            if(remoteCallBack!=null){
                remoteCallBack.callBack(response);
            }
            else{
                int status = response.getStatusLine().getStatusCode();
                if (status == HttpStatus.SC_OK) {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {

                        JSONObject result=null;
                        String resultStr= EntityUtils.toString(entity);
                        try {
                            result=JSONObject.parseObject(resultStr);
                        }
                        catch (Exception e){
                            e.printStackTrace();
                        }

                        return result;
                    }
                }
                else{
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        try {
                            return JSONObject.parseObject(EntityUtils.toString(entity));
                        }
                        catch (Exception e){
                            JSONObject robj=new JSONObject();
                            robj.put("code",-1);
                            robj.put("msg",EntityUtils.toString(entity));
                        }
                    }
                }
            }
        }
        finally {
            if (response != null) {
                try {
                    response.close();
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    public  JSONObject httpPostMethodToJSONObject(ExecutionTypeDO executionTypeDO, HttpMethodEnum httpMethodEnum, String uri, Map<String,Object> parameter, HttpClientTokenDTO httpClientTokenDTO, RemoteCallBack remoteCallBack
            , RemoteProcedureChangeCallService remoteProcedureChangeCallService) throws Exception{

        StringBuilder url=new StringBuilder();
        url.append(httpMethodEnum.value());
        url.append(uri);

        HttpPost httpPost = new HttpPost(url.toString());
        RequestConfig requestConfig=RequestConfig.custom().setConnectTimeout(RpcHttpConfig.connectTimeout).setSocketTimeout(RpcHttpConfig.socketTimeout).build();
        httpPost.setConfig(requestConfig);
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        CloseableHttpResponse response = null;

        try {

            httpPost.setHeader("Content-Type","application/json; charset=utf-8");
            httpPost.setHeader("Connection","close");

            remoteProcedureChangeCallService.changeHttpClientHeaders(httpClientTokenDTO,httpPost,executionTypeDO);

            JSONObject obj=null;
            if(parameter!=null){
                obj= JSONObject.parseObject(JSONObject.toJSONString(parameter));
                String send=obj.toString();
                StringEntity byteArrayEntity=new StringEntity(changeCharset(send,"ISO-8859-1"));
                Header[] header=httpPost.getHeaders("Content-Type");
                if(header!=null && header.length>0){
                    StringBuilder stringBuilder=new StringBuilder();
                    for(int i=0;i<header.length;i++){
                        if(i>0) stringBuilder.append("; ");
                        stringBuilder.append(header[i].getValue());
                    }
                    byteArrayEntity.setContentType(stringBuilder.toString());
                }
                else{
                    byteArrayEntity.setContentType("application/json; charset=utf-8");
                }
                httpPost.setEntity(byteArrayEntity);

            }



            response = httpClient.execute(httpPost);
            if(remoteCallBack!=null){
                remoteCallBack.callBack(response);
            }
            else{
                int status = response.getStatusLine().getStatusCode();
                if (status == HttpStatus.SC_OK) {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {

                        JSONObject result=null;
                        String resultStr= EntityUtils.toString(entity);
                        try {
                            result=JSONObject.parseObject(resultStr);
                        }
                        catch (Exception e){
                            e.printStackTrace();
                        }

                        return result;
                    }
                }
                else{
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        return JSONObject.parseObject(EntityUtils.toString(entity));
                    }
                }
            }
        }
        finally {
            if (response != null) {
                try {
                    response.close();
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    public  JSONObject httpLoingToJSONObject(String url, JSONObject parameter,String token) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig=RequestConfig.custom().setConnectTimeout(RpcHttpConfig.connectTimeout).setSocketTimeout(RpcHttpConfig.socketTimeout).build();
        httpPost.setConfig(requestConfig);
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        CloseableHttpResponse response = null;

        try {

            httpPost.setHeader("Content-Type","application/json; charset=utf-8");
            httpPost.setHeader("Connection","close");
            if(token!=null){
                httpPost.setHeader("authorization",token);
                httpPost.setHeader("Authorization",token);

            }

            JSONObject obj=null;
            if(parameter!=null){
                obj= parameter;
                String send=obj.toString();
                StringEntity byteArrayEntity=new StringEntity(changeCharset(send,"ISO-8859-1"));
                byteArrayEntity.setContentType("application/json");
                httpPost.setEntity(byteArrayEntity);
            }

            response = httpClient.execute(httpPost);
            int status = response.getStatusLine().getStatusCode();
            if (status == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {

                    JSONObject result=null;
                    String resultStr=EntityUtils.toString(entity);
                    try {
                        result=JSONObject.parseObject(resultStr);
                    }
                    catch (Exception e){
                        e.printStackTrace();
                    }

                    return result;
                }
            }
            else{
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    return JSONObject.parseObject(EntityUtils.toString(entity));
                }
            }
        }
        finally {
            if (response != null) {
                try {
                    response.close();
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    public  JSONObject httpPostMethodToJSONObject(ExecutionTypeDO executionTypeDO, HttpMethodEnum httpMethodEnum, String uri, Map<String,Object> parameter, HttpClientTokenDTO httpClientTokenDTO, RemoteCallBack remoteCallBack
            , RemoteProcedureNodeCallService remoteProcedureNodeCallService) throws Exception{

        StringBuilder url=new StringBuilder();
        url.append(httpMethodEnum.value());
        url.append(uri);

        HttpPost httpPost = new HttpPost(url.toString());
        RequestConfig requestConfig=RequestConfig.custom().setConnectTimeout(RpcHttpConfig.connectTimeout).setSocketTimeout(RpcHttpConfig.socketTimeout).build();
        httpPost.setConfig(requestConfig);
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        CloseableHttpResponse response = null;

        try {

            httpPost.setHeader("Content-Type","application/json; charset=utf-8");
            httpPost.setHeader("Connection","close");

            remoteProcedureNodeCallService.changeHttpClientHeaders(httpClientTokenDTO,httpPost,executionTypeDO);

            JSONObject obj=null;
            if(parameter!=null){
                obj= JSONObject.parseObject(JSONObject.toJSONString(parameter));
                String send=obj.toString();
                StringEntity byteArrayEntity=new StringEntity(changeCharset(send,"ISO-8859-1"));
                Header[] header=httpPost.getHeaders("Content-Type");
                if(header!=null && header.length>0){
                    StringBuilder stringBuilder=new StringBuilder();
                    for(int i=0;i<header.length;i++){
                        if(i>0) stringBuilder.append("; ");
                        stringBuilder.append(header[i].getValue());
                    }
                    byteArrayEntity.setContentType(stringBuilder.toString());
                }
                else{
                    byteArrayEntity.setContentType("application/json; charset=utf-8");
                }
                httpPost.setEntity(byteArrayEntity);

            }



            response = httpClient.execute(httpPost);
            if(remoteCallBack!=null){
                remoteCallBack.callBack(response);
            }
            else{
                int status = response.getStatusLine().getStatusCode();
                if (status == HttpStatus.SC_OK) {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {

                        JSONObject result=null;
                        String resultStr= EntityUtils.toString(entity);
                        try {
                            result=JSONObject.parseObject(resultStr);
                        }
                        catch (Exception e){
                            e.printStackTrace();
                        }

                        return result;
                    }
                }
                else{
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        return JSONObject.parseObject(EntityUtils.toString(entity));
                    }
                }
            }
        }
        finally {
            if (response != null) {
                try {
                    response.close();
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}
